DataFusion 之所以在查詢效能上有很大的優勢,很大一部分歸功於 Arrow 這個高效的記憶體格式。今天我們就一起來認識 Arrow,瞭解它在存取資料上的特色與在DataFusion 的定位吧!
Apache Arrow 是一種記憶體格式標準。它定義了資料在記憶體中的佈局方式,專為現代 CPU 運算而設計,從而大幅提高資料處理的速度和效率。那這樣的格式有甚麼神奇的設計原理呢?且聽我娓娓道來~ 以下將分成 3 點介紹 Arrow 的加速機制:
傳統資料格式採用行式(row-based)佈局,將每筆記錄逐行儲存在相鄰記憶體位置 (traditional memory buffer)。列式佈局則是逐列儲存資料 (arrow memory buffer),同一行的資料在記憶體中的位置是連續的,因此在分析查詢場景中 (只需要少數幾個欄位) 可以減少記憶體頻寬使用,同時也支援現代 CPU 向量化的運算 (SIMD),提升處理速度。
SIMD 是 Single Instruction, Multiple Data (單指令,多資料) 的縮寫,是現代 CPU 的一種並行運算技術,讓處理器能在一個指令週期內同時處理多個資料元素。我們舉個簡單的加法運算為例:
傳統標量運算 (Scalar) CPU 需要透過 3 個指令週期來完成以下運算
CPU 暫存器(32位元):
指令1: [ 1200 ] + [ 100 ] = [ 1300 ] ← 1個運算
指令2: [ 500 ] + [ 50 ] = [ 550 ] ← 1個運算
指令3: [ 800 ] + [ 80 ] = [ 880 ] ← 1個運算
而 SIMD 向量運算 (Vector) 可以透過單一指令對多個整數同時進行運算
CPU 暫存器(256位元 AVX2):
指令1: [1200|500|800|300|...] + [100|50|80|30|...] = [1300|550|880|330|...]
↑8個32位元整數同時運算↑
因此搭配上述 Arrow 的列式佈局可以快速且大量的運算多筆資料。
在沒有公開的格式標準之前,不同的資料庫或系統需要定義內部存取的格式或資料結構,因此資料在不同系統間的傳遞需要多次的複製或序列/反序列化,增加了效能成本和資料轉換的複雜度。
當所有的系統都採用 Arrow 的統一的記憶體格式後,便能以最小的開銷移動或轉換資料,資料在記憶體中可以直接引用傳遞,避免昂貴的序列化和反序列化操作 (零拷貝)。
說了這麼多 Arrow 的特色,那 DataFusion 和 Arrow 的關係到底是甚麼呢? 其實 DataFusion 在讀取、查詢或運算資料時,都是基於 Arrow 的格式呦! 具體使用方式大致如下:
換句話說,DataFusion 就是一個專門為 Arrow 格式設計的查詢引擎,兩者完美融合,缺一不可!在後面講解原始碼的文章中應該也會經常出現 Arrow 的身影,到時再詳細的介紹囉!